package org.kalai.unifypay.servlet;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.kalai.unifypay.Constant;
import org.kalai.unifypay.SessionManager;
import org.kalai.unifypay.bean.Bizcnf;
import org.kalai.unifypay.bean.Member;
import org.kalai.unifypay.bean.Transflow;
import org.kalai.unifypay.util.CipherUtils;
import org.kalai.unifypay.util.CommonUtil;
import org.kalai.unifypay.util.DataDao;
import org.kalai.unifypay.util.ProxyPayUtil;

import com.alibaba.fastjson.JSON;

/**
 * 异步通知逻辑处理(民生通道)
 * 
 * @author zsl-2016年9月24日(修改)
 *
 */
@WebServlet(urlPatterns = "/AlipayNotify")
public class MinsNotify extends HttpServlet {

   private static final long   serialVersionUID = 4553766925571289786L;

   private static final Logger logger           = Logger.getLogger(MinsNotify.class);

   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      CommonUtil.responseObject(resp, Constant.ERROR_REQEST);
   }

   @Override
   protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      /* 获取请求参数 */
      String encryptData = request.getParameter("encryptData");
      String encryptKey = request.getParameter("encryptKey");
      String signData = request.getParameter("signData");
      String tranxSN = request.getParameter("reqMsgId");
      String aesKey = CipherUtils.decryptRSA(CipherUtils.decryptBase64(encryptKey));
      String xmlMessage = CipherUtils.decryptAES(CipherUtils.decryptBase64(encryptData), aesKey);
      try {
         /* 验证签名 */
         boolean flag = CipherUtils.designRSA(CipherUtils.decryptBase64(signData), xmlMessage);
         if (!flag)
            throw new RuntimeException("验证签名失败！");

         // 查询订单信息
         Transflow transflow = DataDao.getInstance().getTransflow(tranxSN);
         if (transflow == null)
            throw new RuntimeException("订单查询为空");

         /* 参数转换 */
         String respCode = xmlMessage.substring(xmlMessage.indexOf("<respCode>") + 10, xmlMessage.indexOf("</respCode>"));
         String respDesc = xmlMessage.substring(xmlMessage.indexOf("<respMsg>") + 9, xmlMessage.indexOf("</respMsg>"));
         String payAccount = xmlMessage.substring(xmlMessage.indexOf("<buyerAccount>") + 14,
               xmlMessage.indexOf("</buyerAccount>"));
         String buyerPayAmount = xmlMessage.substring(xmlMessage.indexOf("<buyerPayAmount>") + 16,
               xmlMessage.indexOf("</buyerPayAmount>"));
         logger.info(String.format("接收到民生异步通知[%s-%s-%s-%s]", tranxSN, buyerPayAmount, respCode, respDesc));

         /* 处理异步通知 */
         Map<String, Object> params = new HashMap<String, Object>();
         params.put("tranxSN", tranxSN);
         params.put("oriRespCode", respCode);
         params.put("oriRespMsg", respDesc);
         params.put("buyerAccount", payAccount);
         params.put("buyerPayAmount", buyerPayAmount);

         new MinsNotify().notifyManage(transflow, params);

      } catch (Exception e) {
         logger.error(String.format("(民生)异步通知异常:参数xmlMessage=[%s],异常详情:%s", xmlMessage, e));
      } finally {
         CommonUtil.responseObject(response, "000000");
      }
   }

   /**
    * 处理异步通知
    * 
    * @param transflow
    * @param params
    * @throws Exception
    */
   public void notifyManage(Transflow transflow, Map<String, Object> params) throws Exception {
      if (transflow == null)
         throw new RuntimeException(String.format("交易信息为空,接收民生参数:%s", params));

      /* 支付中的订单才进行处理 */
      if (transflow.getStatus() == 1) {

         /* 查询商户信息是否存在 */
         Member member = DataDao.getInstance().getMember(transflow.getMemberNo());
         if (member == null)
            throw new RuntimeException("商户信息不存在:" + transflow.getMemberNo());
         /* 断言参数 */
         Double buyerPayAmount = 0.0;
         String buyerAccount = "";
         if (params.get("buyerPayAmount") != null) {
            buyerPayAmount = Double.valueOf((String) params.get("buyerPayAmount")) * 100;
         }
         if (params.get("buyerAccount") != null) {
            buyerAccount = params.get("buyerAccount").toString();
         }

         /* 更新交易表 */
         String respCode = "000000".equals(params.get("oriRespCode")) ? "00" : (String) params.get("oriRespCode");
         boolean isok = "00".equals(respCode);

         DataDao.getInstance().updateTransflow(transflow.getTranxSN(), buyerAccount, buyerPayAmount.longValue(), isok ? 2 : 3,
               respCode, isok ? "交易成功" : params.get("oriRespMsg"));

         /* D0交易成功后实时代付出去 */
         String bizcode = transflow.getBizcode();
         Bizcnf bizcnf = DataDao.getInstance().getBizcnfByCode(bizcode);
         if (isok && bizcnf.getPattern() == 0) {
            String settNo = CommonUtil.generSettNo();
            boolean rs = DataDao.getInstance().addSettlement(transflow.getTranxSN(), settNo, bizcode, member,
                  transflow.getTransAmt() - transflow.getTransFee(), 1);
            if (rs)
               ProxyPayUtil.proxyPay(settNo, member,
                     ((Double) (transflow.getTransAmt() * 100 - transflow.getTransFee() * 100)).longValue(), bizcode, true);
         }
         // 异步通知账单系统
         CommonUtil.notifyTransFlow(transflow);
         /* 异步通知合作方 */
         String url = transflow.getNotifyUrl();
         String partnerCode = transflow.getPartnerCode();
         String secret = DataDao.getInstance().getPartnerByCode(partnerCode).getPartnerSecret();
         if (url != null && !"".equals(url))
            CommonUtil.notifyMessage(url, partnerCode, secret, transflow.getTranxSN(), transflow.getOrderNo(),
                  transflow.getTransAmt(), respCode, (String) params.get("oriRespMsg"));

         /* websocket推送消息 */
         Map<String, Object> result = CommonUtil.createRespMap(respCode, (String) params.get("oriRespMsg"));
         SessionManager.getInstance().broadcast(transflow.getTranxSN(), JSON.toJSONString(result));
      } else {
         throw new RuntimeException(transflow.getTranxSN() + "订单状态异常status=" + transflow.getStatus());
      }
   }
}
